# -*-coding:utf-8-*-
import os
import sys
import uuid
import socket
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from JS_widgets.DeepWindow import DeepWindow

class PaitItem(QGraphicsItem):
    def __init__(self,uid,rect,color,scenePos,attr,deep):
        super(PaitItem, self).__init__()
        self.uid = uid
        self.rect=rect
        self.color=color
        self.attr=attr
        self.deep=deep
        # self.setPos(scenePos)
        self.setAcceptDrops(True)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)

    def boundingRect(self):
        # if self.customLength > 0:
        #     self.width=self.customLength*self.ui_width#
        # return QRectF(0, 0, (self.width / self.scale()) - 20, self.height / self.scale())
        return self.rect

    def paint(self, QPainter, QStyleOptionGraphicsItem, widget=None):
        # 选中状态变色
        pen = QPen()
        if self.isSelected():
            # print('SSS')
            pen.setColor(QColor('#B0C4DE'))
            pen.setWidth(2)
        QPainter.setPen(pen)
        QPainter.setBrush(QBrush(QColor(self.color)))
        QPainter.drawRect(self.rect)
        QPainter.drawText(self.rect, Qt.AlignCenter, self.deep)


    def contextMenuEvent(self, QGraphicsSceneContextMenuEvent):
        rMenu = QMenu()
        deep_action = QAction(u'设置深度    D', None)
        deep_action.triggered.connect(self.set_deep)

        style_action=QAction('风格    S',None)
        style_action.triggered.connect(self.set_style)
        rMenu.addAction(deep_action)
        rMenu.exec(QGraphicsSceneContextMenuEvent.screenPos())


    def set_deep(self):
        self.deep_window=DeepWindow()
        self.deep_window.deep_Signal.connect(self._set_deep)
        self.deep_window.show()

    def _set_deep(self,deep):
        sn = self.scene.selectedItems()
        self.deep=deep
        self.setZValue(deep)
        self.update()

    def set_style(self):
        print('风格窗口选择')

    def set_scale(self,direct,factor):
        if direct=='R':
            self.rect.setRight(self.rect.right() + factor)
        if direct=='L':
            self.rect.setRight(self.rect.right() - factor)
        if direct=='U':
            self.rect.setTop(self.rect.top() - factor)  #这里是反的
        if direct=='D':
            self.rect.setTop(self.rect.top() + factor)
            self.boundingRect()
        self.update()

    def wheelEvent(self, QGraphicsSceneWheelEvent):
        try:
            factor = QGraphicsSceneWheelEvent.delta() / 120.0

            if QGraphicsSceneWheelEvent.delta() / 120.0 > 0:
                factor = 1.2
            else:
                factor = 0.9
            print('factor:',factor)
            self.setScale(self.scale()*factor)
        except Exception as wheelEvent_ERR:
            print(str(wheelEvent_ERR))

        super(PaitItem, self).wheelEvent(QGraphicsSceneWheelEvent)


class ImageItem(QGraphicsItem):
    def __init__(self,uid,rect,color,attr,deep):
        super(ImageItem, self).__init__()
        self.uid=uid
        self.rect=rect
        self.color=color
        # self.img=img
        self.attr=attr
        self.deep=deep
        self.setAcceptDrops(True)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)
        self.data={'uuid':self.uid,'rect':self.rect,'pos':self.pos(),'attr':self.attr,'deep':self.deep}

    def boundingRect(self):
        # if self.customLength > 0:
        #     self.width=self.customLength*self.ui_width#
        # return QRectF(0, 0, (self.width / self.scale()) - 20, self.height / self.scale())
        return self.rect

    def paint(self, QPainter, QStyleOptionGraphicsItem, widget=None):
        # 选中状态变色
        pen = QPen()
        if self.isSelected():
            # print('SSS')
            pen.setColor(QColor('#B0C4DE'))
            pen.setWidth(2)
        font = QFont('', 15)
        QPainter.setPen(pen)

        QPainter.setFont(font)
        QPainter.setBrush(QBrush(QColor(self.color)))
        QPainter.drawRect(self.rect)
        img=QPixmap(self.attr['path'])
        QPainter.drawPixmap(0, 0, self.rect.width(), self.rect.height(), img)
        QPainter.drawText(self.rect, Qt.AlignCenter, self.deep)


        # QPainter.drawPixmap(self.rect,img)
        # QRectF

    def contextMenuEvent(self, QGraphicsSceneContextMenuEvent):
        rMenu = QMenu()
        deep_action = QAction(u'设置深度    D', None)
        deep_action.triggered.connect(self.set_deep)

        style_action=QAction('风格    S',None)
        style_action.triggered.connect(self.set_style)
        rMenu.addAction(deep_action)
        rMenu.exec(QGraphicsSceneContextMenuEvent.screenPos())


    def set_deep(self):
        self.deep_window=DeepWindow()
        self.deep_window.deep_Signal.connect(self._set_deep)
        self.deep_window.show()

    def _set_deep(self,deep):
        sn = self.scene.selectedItems()
        self.deep=deep
        self.setZValue(deep)
        self.update()

    def set_style(self):
        print('风格窗口选择')

    def set_scale(self,direct,factor):
        if direct=='R':
            self.rect.setRight(self.rect.right() + factor)
        if direct=='L':
            self.rect.setRight(self.rect.right() - factor)
        if direct=='U':
            self.rect.setTop(self.rect.top() - factor)  #这里是反的
        if direct=='D':
            self.rect.setTop(self.rect.top() + factor)
            self.boundingRect()
        self.update()

    def wheelEvent(self, QGraphicsSceneWheelEvent):
        try:
            factor = QGraphicsSceneWheelEvent.delta() / 120.0

            if QGraphicsSceneWheelEvent.delta() / 120.0 > 0:
                factor = 1.2
            else:
                factor = 0.9
            print('factor:',factor)
            self.setScale(self.scale()*factor)
        except Exception as wheelEvent_ERR:
            print(str(wheelEvent_ERR))

        super(PaitItem, self).wheelEvent(QGraphicsSceneWheelEvent)

    def update_pos(self):
        print('更新自己的信息:',self.uid)
        print('位置变化为:',self.pos())
    def update_for_GC(self):
        # scenc_scale=  self.scene.sceneRect()
        # print('scenc_scale:',scenc_scale)

        scene=self.scene()
        width=scene.width()
        height=scene.height()
        print('scen：', width,height)
        t_rect = (self.rect.x(), self.rect.y(), self.rect.width(), self.rect.height())
        position = (self.pos().x(), self.pos().y())
        self.data = {'uuid': self.uid, 'rect': t_rect, 'pos': position, 'attr': self.attr, 'deep': self.deep}
        print('data:',self.data)

class CurveItem(QGraphicsItem):
    def __init__(self,rect,path,color):
        super(CurveItem, self).__init__()
        self.color=color
        self.setAcceptDrops(True)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)
        self.rect=rect
        self.path=path

    def boundingRect(self):
        return self.rect

    def paint(self, QPainter, QStyleOptionGraphicsItem, widget=None):
        pen=QPen()
        if self.isSelected():
            pen.setColor(QColor('#FFFFF0'))
            pen.setWidth(2)
        QPainter.setBrush(QBrush(QColor(self.color)))
        # QPainter.drawPath(self.path)
        QPainter.drawRect(self.rect)

class CenterItem(QGraphicsItem):
    def __init__(self):
        super(CenterItem, self).__init__()
        self.setAcceptDrops(True)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        # self.setFlag(QGraphicsItem.ItemIsMovable, True)
        self.rect=QRectF(0,0,5,5)

    def boundingRect(self):
        return self.rect

    def paint(self, QPainter, QStyleOptionGraphicsItem, widget=None):
        # 选中状态变色
        pen = QPen()
        if self.isSelected():
            pen.setColor(QColor('#FFFFF0'))
            pen.setWidth(2)
        QPainter.setBrush(QBrush(QColor('#BEBEBE')))
        # QPainter.drawRect(self.rect)
        QPainter.drawEllipse(self.rect)


class GraphicView(QGraphicsView):
    # current_artist_Signal = pyqtSignal(str)

    def __init__(self,parent=None):
        super(GraphicView, self).__init__(parent)
        #全局变量
        self.HOST='192.168.53.3'
        self.PORT = 2021
        self.BUFFER = 10240
        self.current_scene_pos=None  #当前鼠标点击点
        self.release_pos= None  #当前鼠标释放后的位置
        self.color_map={'Ground':'#5d422d','Sea':'#1d5291','River':'#798ba0','Mountain':'#d8b783','Grass':'#5bed1d','Sky':'#a0eef3'}
        self.w=self.h=1000
        self.begin_draw=False #开始绘制
        self.draw_points=[]  #每次点击的点
        self.drawing=-1  #当前是否处于绘制模式

        # self.setMaximumSize(1920, 1080)
        # self.setFixedSize(1920,1080)
        self.setMinimumWidth(self.w)
        self.setMinimumHeight(self.h)
        self.setDragMode(QGraphicsView.RubberBandDrag)
        self.setRenderHint(QPainter.Antialiasing)
        self.setRenderHint(QPainter.TextAntialiasing)
        self.setStyleSheet("padding:0px;border:0px")
        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)  # 全视图，可以消除残影
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setMouseTracking(1)
        self.setAcceptDrops(True)
        self.scene=QGraphicsScene()

        self.setScene(self.scene)
        self.scene.setSceneRect(QRectF(0,0,self.w,self.h))
        self.init_center()


    def init_center(self):
        center_item=CenterItem()
        self.scene.addItem(center_item)
        s_pos=self.mapToScene(self.w/2,self.h/2)
        center_item.setPos(s_pos)

    def forGC(self,data):
        """
        将需要生成的数据发射给GC
        data：{'uuid1':data1,'uuid2':data2,'uuid3':data3,...}
        :return:
        """
        print('将信息发射给GC进行推演:',data)
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(0.55)
        try:
            sock.connect((self.HOST, self.PORT))

            sock.send(str(data).encode('utf8'))
            back = sock.recv(self.BUFFER)
            print('send')
            if back:
                data = eval(back.decode('utf8'))
                print('back:',data)
        except Exception as request_from_222_ERR:
            print('request failed')
            print(str(request_from_222_ERR))
        finally:
            sock.close()


    def mousePressEvent(self, QMouseEvent):
        if QMouseEvent.button()==Qt.LeftButton:
            current_Pos = QMouseEvent.pos()
            scenePos = self.mapToScene(current_Pos)
            print('scenePos:',scenePos.x(),scenePos.y())
            # scenePos=QMouseEvent.scenePos()
            self.current_scene_pos=scenePos

            # if self.parent().parent().draw_type == 'curve' and self.:
            #     if self.begin_draw==False:
            #         self.begin_draw=True
            #         self.draw_points.append(scenePos)
            #     else:
            #         self.draw_points.append(scenePos)



        #             # print('draw curve')
        #             # path=QPainterPath()
        #             # path.moveTo(0,0)
        #             # path.cubicTo(self.draw_points)
        #             # self.scene.addPath(path)
        #
        # if QMouseEvent.button()==Qt.RightButton:
        #     if self.begin_draw:
        #         current_Pos = QMouseEvent.pos()
        #         scenePos = self.mapToScene(current_Pos)
        #         print('draw curve')
        #         path = QPainterPath()
        #         path.moveTo(0, 0)
        #         draw_points_list=[]
        #         draw_points_x=[]
        #         draw_points_y=[]
        #         for i in self.draw_points:  #这里面都是场景坐标
        #             draw_points_list.append(i.x())
        #             draw_points_x.append(i.x())
        #             draw_points_list.append(i.y())
        #             draw_points_y.append(i.y())
        #         minx=min(draw_points_x)
        #         maxx=max(draw_points_x)
        #         miny=min(draw_points_y)
        #         maxy=max(draw_points_y)
        #
        #         center_x=sum(draw_points_x)/len(draw_points_x)
        #         center_y = sum(draw_points_y) / len(draw_points_y)
        #
        #         start_p=QPointF(minx,maxy)
        #         r_p=QPointF(minx,maxy/2)
        #         end_p=QPointF(maxx,miny)
        #
        #         center_p=QPointF(center_x,center_y)
        #         # rect=QRectF(start_p-center_p,end_p-center_p)
        #         # rect=QRectF(minx-center_x,maxy-center_y,maxx-center_x,miny-center_y)  #因为坐标从左上角算，所以bound是最小的x与最大的y为起始。最大的x与最小的y为终点，bound算法是对的
        #         rect=QRectF(0,0,maxx-minx,maxy-miny)  #rect只求宽度，高度，从0，0开始
        #         # print(draw_points_list)
        #         # path.cubicTo(*draw_points_list)
        #
        #         # path.cubicTo(100, -20, 40, 90, 20, 20)#,50,140,90,72
        #         # self.scene.addPath(path)
        #         # self.scene.addPolygon(polyon)
        #
        #         polyon=QPolygonF(self.draw_points)
        #         path.addPolygon(polyon)
        #         curve_item=CurveItem(rect,path,'#4169E1')
        #         # new_x = scenePos.x() - rect.x()
        #         # new_y = scenePos.y() - rect.y()
        #         # new_pos = QPointF(new_x, new_y)
        #         self.scene.addItem(curve_item)
        #         curve_item.setPos(r_p)
        #
        #         self.begin_draw=False
        #         self.draw_points.clear()
        #         # self.scene.addPath(path)
        #         # print(self.draw_points)
        #
        #         # self.scene.addPath(path)
        #         # self.begin_draw=False

        super(GraphicView, self).mousePressEvent(QMouseEvent)



    def mouseReleaseEvent(self, QMouseEvent):
        item=None
        new_pos=None
        if QMouseEvent.button()==Qt.LeftButton:
            # print("LEFT")
            # print(self.parent().parent())
            if self.parent().parent().drawing == -1:  #-1绘制，1为移动

                current_Pos = QMouseEvent.pos()
                scenePos = self.mapToScene(current_Pos)
                # self.release_pos=scenePos
                print('scenePos:',scenePos,type(scenePos))
                dx=scenePos.x()-self.current_scene_pos.x()
                # print(dx)
                dy=scenePos.y()-self.current_scene_pos.y()
                # print(dy)
                if abs(dx)>5 and abs(dy)>5:
                    rect=QRectF(0, 0, dx, dy)
                    new_x=scenePos.x()-abs(dx)
                    new_y=scenePos.y()-abs(dy)
                    new_pos=QPointF(new_x,new_y)
                    current_attr=self.parent().parent().current_attr
                    current_deep=self.parent().parent().current_deep
                    if not current_attr:  # 当没有绘图时，就只是boundbox
                        uid=str(uuid.uuid1())
                        item=PaitItem(uid,rect,'#FFDEAD',new_pos,current_attr,current_deep)
                        self.scene.addItem(item)
                        item.setPos(new_pos)
                        t_rect=(rect.x(),rect.y(),rect.width(),rect.height())
                        position=(new_pos.x(),new_pos.y())
                        data = {'uuid': uid, 'rect': t_rect, 'pos': position, 'attr': current_attr, 'deep': current_deep}
                        self.forGC(data)
                        # item.update_for_GC()
                    else:
                        print('rect:',rect)
                        try:
                            uid = str(uuid.uuid1())
                            item=ImageItem(uid,rect,'#FFDEAD',current_attr,current_deep)
                            self.scene.addItem(item)
                            item.setPos(new_pos)
                            t_rect = (rect.x(), rect.y(), rect.width(), rect.height())
                            position = (new_pos.x(), new_pos.y())
                            data = {'uuid': uid, 'rect': t_rect, 'pos': position, 'attr': current_attr,
                                    'deep': current_deep}
                            self.forGC(data)
                        except Exception as imgItem_ERR:
                            print(str(imgItem_ERR))

            else: #当是移动时
                items=self.scene.selectedItems()
                if items:
                    for i in items:
                        i.update_for_GC()
                        self.forGC(i.data)

        super(GraphicView, self).mouseReleaseEvent(QMouseEvent)


    def set_deep(self):
        self.deep_window=DeepWindow()
        self.deep_window.deep_Signal.connect(self._set_deep)
        self.deep_window.show()

    def _set_deep(self,deep):
        sn = self.scene.selectedItems()
        if sn:
            for n in sn:
                if isinstance(n, PaitItem):
                    # print(n)
                    n.deep=deep

    def scale_bound(self,direct,factor):
        sn = self.scene.selectedItems()
        if sn:
            for n in sn:
                if isinstance(n, PaitItem):
                    n.set_scale(direct,factor)

    def keyPressEvent(self, QKeyEvent):
        if QKeyEvent.key()==Qt.Key_Delete or QKeyEvent.key()==Qt.Key_Backspace:
            sn=self.scene.selectedItems()
            if sn:
                for n in sn:
                    self.scene.removeItem(n)

        if QKeyEvent.key()==Qt.Key_QuoteLeft:
            self.parent().parent()._set_move()

        if QKeyEvent.key() == Qt.Key_D:
            self.set_deep()

        if QKeyEvent.key()==Qt.Key_Right:
            if QKeyEvent.modifiers() & Qt.ShiftModifier:
                self.scale_bound('R', 10)
            else:
                self.scale_bound('R', 1.5)
        if QKeyEvent.key()==Qt.Key_Left:
            if QKeyEvent.modifiers() & Qt.ShiftModifier:
                self.scale_bound('L', 10)
            else:
                self.scale_bound('L', 1.5)
        if QKeyEvent.key()==Qt.Key_Up:
            if QKeyEvent.modifiers() & Qt.ShiftModifier:
                self.scale_bound('U', 10)
            else:
                self.scale_bound('U', 1.5)
        if QKeyEvent.key()==Qt.Key_Down:
            if QKeyEvent.modifiers() & Qt.ShiftModifier:
                self.scale_bound('D', 10)
            else:
                self.scale_bound('D', 1.5)

        if QKeyEvent.key()==Qt.Key_Escape:
            self.current_scene_pos


        super(GraphicView, self).keyPressEvent(QKeyEvent)